#ifndef RWLock_INCLUDED
#define RWLock_INCLUDED

#include <pthread.h>
#include <errno.h>

class RWLock
{
public:
    RWLock();
        
    ~RWLock();
    
    void readLock();

    bool tryReadLock();

    void writeLock();

    bool tryWriteLock();

    void unlock();

private:
    RWLock(const RWLock&);
    RWLock& operator = (const RWLock&);
private:
    pthread_rwlock_t m_rwl;
};

class ScopedRWLock
{
public:
    ScopedRWLock(RWLock& rwl, bool write = false);
    ~ScopedRWLock();

private:
    RWLock& m_rwl;

    ScopedRWLock();
    ScopedRWLock(const ScopedRWLock&);
    ScopedRWLock& operator = (const ScopedRWLock&);
};

class ScopedReadRWLock : public ScopedRWLock
{
public:
    ScopedReadRWLock(RWLock& rwl);
    ~ScopedReadRWLock();
};

class ScopedWriteRWLock : public ScopedRWLock
{
public:
    ScopedWriteRWLock(RWLock& rwl);
    ~ScopedWriteRWLock();
};

//
// inlines
//
inline void RWLock::readLock()
{
    pthread_rwlock_rdlock(&m_rwl);
}

inline bool RWLock::tryReadLock()
{
    int rc = pthread_rwlock_tryrdlock(&m_rwl);
    if (rc == 0)
        return true;
    else if (rc == EBUSY)
        return false;

    return false;
}

inline void RWLock::writeLock()
{
    pthread_rwlock_wrlock(&m_rwl);
}

inline bool RWLock::tryWriteLock()
{
    int rc = pthread_rwlock_trywrlock(&m_rwl);
    if (rc == 0)
        return true;
    else if (rc == EBUSY)
        return false;

    return false;
}

inline void RWLock::unlock()
{
    pthread_rwlock_unlock(&m_rwl);
}

inline ScopedRWLock::ScopedRWLock(RWLock& rwl, bool write): m_rwl(rwl)
{
    if (write)
        m_rwl.writeLock();
    else
        m_rwl.readLock();
}

inline ScopedRWLock::~ScopedRWLock()
{
    m_rwl.unlock();
}

inline ScopedReadRWLock::ScopedReadRWLock(RWLock& rwl): ScopedRWLock(rwl, false)
{
}

inline ScopedReadRWLock::~ScopedReadRWLock()
{
}

inline ScopedWriteRWLock::ScopedWriteRWLock(RWLock& rwl): ScopedRWLock(rwl, true)
{
}

inline ScopedWriteRWLock::~ScopedWriteRWLock()
{
}

#endif







